import { VxeUI } from 'vxe-pc-ui';
import { markRaw, nextTick } from 'vue';
import { defineStore } from '@/config/pinia/index.ts';
import { useMenusStore } from '@/config/pinia/menus.store.ts';
import type { CommonMenuProps } from '#/Menu.d.ts';
import { getComponent } from '@/config/component/component.ts';
import { recursionFind } from '@/config/utils/utils.ts';
import { homeCode } from '@/config/pinia/menus.store.config.ts';
const menusStore = useMenusStore();
export const useTabsStore = defineStore({
	id      : 'tabsStore',
	state   : () => {
		return {
			// Tab框的数组
			tabs : [] as Array<CommonMenuProps>,
			// 当前选中的Tab['code']
			currentActivatedTab : null as string | number | null,
			// 当前右键选择的Tab框
			currentSelectedTab : null as CommonMenuProps | null
		};
	},
	actions : {
		/**
		 * 根据传递的Tab对象来添加标签页
		 * @param menu 添加的对象
		 */
		async addTab(menu: CommonMenuProps): Promise<void> {
			this.pushTab(menu).then((addedTab: CommonMenuProps | void): void => {
				if (addedTab) {
					// 添加完Tab之后设置浏览器当前展示的组件对象
					// menusStore.currentActivateComponent = addedTab;
					// 同步到会话存储中
					this.syncTabsToSession();
				}
			}).catch(error => {
				console.error(error);
				VxeUI.modal.message({
					content : '组件处理异常,请尝试修复子组件或页面',
					status  : 'error',
					id      : 'errorMessage'
				});
			});
		},
		/**
		 * 加入标签
		 * <br/>
		 * 加入标签有2种情况
		 * <br/>
		 * 1:标签已经存在,则将其前置
		 * <br/>
		 * 2:标签不存在,则创建新标签并将其前置
		 * @param menu 添加的对象
		 */
		async pushTab(menu: CommonMenuProps): Promise<CommonMenuProps | void> {
			// 从tabs中寻找相同code的标签
			const existingTab: CommonMenuProps | undefined =
					  this['tabs'].find((item: CommonMenuProps): boolean => item.menuCode === menu.menuCode);
			// 检查标签是否已存在
			if (existingTab) {
				// 如果已经存在且[需要]强制刷新
				if (menu['forceFlush']) {
					// 在key后面添加0-10000之间的随机数,让组件自行刷新
					existingTab['key'] = `${existingTab.menuCode}_${Math.ceil(Math.random() * 10000)}`;
				}
				// 将已存在标签前置
				this['currentActivatedTab'] = menu.menuCode;
				return Promise.resolve(existingTab);
			} else {
				// 检查tabs是否存在10个,已有10个则提醒用户关闭掉一些
				if (!(10 > this['tabs'].length)) {
					await VxeUI.modal.message(
						{
							content : `您已开启10个标签了,为了浏览器的流畅度着想,请您先关闭掉一些不用的标签`,
							status  : 'warning',
							id      : 'tabTooManyMessage'
						}
					);
					return;
				}
				// 如果不存在,那么直接添加一个新的Tab
				const newTab: CommonMenuProps = {
					id           : menu.id,
					key          : menu.menuCode,
					menuCode     : menu.menuCode,
					menuName     : menu.menuName,
					menuType     : menu.menuType,
					menuPath     : menu.menuPath,
					menuIcon     : menu.menuIcon ? menu.menuIcon : '',
					menuIconType : menu.menuIconType ? menu.menuIconType : '',
					tabIcon      : menu.tabIcon ? menu.tabIcon : '',
					tabIconType  : menu.tabIconType ? menu.tabIconType : '',
					isCache      : menu.isCache ? menu.isCache : false,
					params       : menu.params ? menu.params : undefined,
					forceFlush   : menu.forceFlush ? menu.forceFlush : false,
					component    : markRaw(getComponent(menu.menuPath))
				};
				this['tabs'].push(newTab);
				// 把当前激活的Tab设置为新添加的标签
				this['currentActivatedTab'] = menu.menuCode;
				return Promise.resolve(newTab);
			}
		},
		/**
		 * 移除单个标签
		 * <br/>
		 * 移除标签有2种情况
		 * <br/>
		 * 1:移除当前激活的标签
		 * <br/>
		 * 2:移除非激活的标签
		 * <br/>
		 * 且移除的时候需要将事件也一同移除
		 * @param menuCode 标签页的code
		 */
		async removeTab(menuCode: string | number): Promise<void> {
			// 判断是否存在Tabs,不存在的话就是调用的会话中的Tab
			if (this['tabs'] && this['tabs'].length) {
				// tabs存在且有值
				this['tabs'].forEach((menu: CommonMenuProps, index: number): void => {
					// 判断是否遍历到了需要移除的标签对象
					if (menu.menuCode === menuCode) {
						// 如果移除的是当前激活页,还需要处理下相邻标签页进行补位
						if (this['currentActivatedTab'] === menuCode) {
							// 关闭当前激活页后还需要让相邻的Tab来补位
							const nextTab = this['tabs'][index + 1] || this['tabs'][index - 1];
							// 如果相邻的标签对象存在
							if (nextTab) {
								// 设置当前激活的Tab
								this['currentActivatedTab'] = nextTab.menuCode;
								// 设置当前激活组件
								// menusStore.currentActivateComponent = nextTab;
							}
						}
						// 通过splice精准清除掉标签页
						this['tabs'].splice(index, 1);
						return;
					}
				});
				// 同步数据到会话中
				await this.syncTabsToSession();
			} else {
				// TODO 删除会话存储中的标签
				// TODO 针对于某种特殊场景
				// TODO 比如在另一个全局路由页面上,
				//  然后它单击某按钮跳回到index页之前,
				//  要求把某页面关闭,
				//  此时可以用该方法关闭在sessionStorage中存储的页面
				await this.removeSessionTab();
			}
		},
		/**
		 * 切换当前激活组件
		 * @param menuCode Tab的code属性
		 */
		/*async changeCurrentActivateComponent(menuCode: string | number): Promise<void> {
		 menusStore['currentActivateComponent'] =
		 this['tabs'].find((menu: CommonMenuProps): boolean => menu.menuCode === menuCode);
		 },*/
		/**
		 * 刷新指定的标签页
		 * <br/>
		 * 使其组件内部的所有元素重绘和生命周期重新执行
		 * <br/>
		 * ~~~
		 * 优雅刷新
		 * ~~~
		 * @param menuCode Tab的code属性
		 */
		async refreshTab(menuCode: string): Promise<void> {
			if (menuCode) {
				const refreshTarget: CommonMenuProps | undefined =
						  this['tabs'].find((menu: CommonMenuProps): boolean => menu.menuCode === menuCode);
				refreshTarget!['key'] = `${refreshTarget!.menuCode}_${Math.ceil(Math.random() * 10000)}`;
			}
		},
		/**
		 * 移除所选标签页之外的所有标签页(除首页外)
		 */
		async removeOtherTabs(): Promise<string> {
			// 获取右键所选标签
			const menuCode: string = this.currentSelectedTab!.menuCode;
			// 匹配标签
			this['tabs'] = this['tabs'].filter((menu: CommonMenuProps) => {
				// 如果是首页菜单,或者是目标菜单,就留下来,其他全剔除
				return homeCode === menu.menuCode || menuCode === menu.menuCode;
			});
			return menuCode;
		},
		/**
		 * 移除所有标签页(除首页外)
		 */
		async removeAllTabs(): Promise<string> {
			this['tabs'] = this['tabs'].filter((menu: CommonMenuProps) => {
				return homeCode === menu.menuCode;
			});
			return homeCode;
		},
		/**
		 * 删除会话中的标签
		 */
		async removeSessionTab(): Promise<void> {
		},
		/**
		 * 同步tabs和currentActivatedTab到会话存储中
		 */
		async syncTabsToSession(): Promise<void> {
			sessionStorage.setItem('tabs', JSON.stringify(this['tabs']));
			sessionStorage.setItem('currentActivatedTab', JSON.stringify(this['currentActivatedTab']));
		},
		/**
		 * 从会话存储中同步tabs和currentActivatedTab到Store中
		 * 如果传递了menu参数,则强制同步一下菜单属性到会话中
		 */
		async syncSessionTabsToStore(): Promise<void> {
			const tabsStr: string | null = sessionStorage.getItem('tabs');
			const currentActivatedTabStr: string | null = sessionStorage.getItem('currentActivatedTab');
			if (tabsStr) {
				// component需要重新初始化,在会话存储中无法存储
				const sessionTabs: Array<CommonMenuProps> = JSON.parse(tabsStr);
				sessionTabs.forEach((item: CommonMenuProps): void => {
					// 重建组件
					// 将会话中的标签与最新的菜单信息数据对齐
					Object.assign(item, {
						id           : item.id,
						key          : item.menuCode,
						menuCode     : item.menuCode,
						menuName     : item.menuName,
						menuType     : item.menuType,
						menuPath     : item.menuPath,
						menuIcon     : item.menuIcon ? item.menuIcon : '',
						menuIconType : item.menuIconType ? item.menuIconType : '',
						tabIcon      : item.tabIcon ? item.tabIcon : '',
						tabIconType  : item.tabIconType ? item.tabIconType : '',
						isCache      : item.isCache ? item.isCache : false,
						params       : item.params ? item.params : undefined,
						forceFlush   : item.forceFlush ? item.forceFlush : false,
						component    : markRaw(getComponent(item.menuPath))
					});
				});
				this['tabs'] = sessionTabs;
			}
			if (currentActivatedTabStr) {
				// 此处因为naive-ui的某些奇葩问题导致不会更新当前激活的标签页内容
				// 所以必须要以下列形式切换一下当前激活的标签页
				await nextTick((): void => {
					// 将右键所选标签设置为当前激活的标签页
					this['currentActivatedTab'] = JSON.parse(currentActivatedTabStr);
					// this['currentActivatedTab'] = '';
				}).catch(error => {
					console.log(error);
				});/*.then((): void => {
				 // this['currentActivatedTab'] = JSON.parse(currentActivatedTabStr);
				 });*/
			}
		}
	},
	getters : {}
});